// v2010.09.21

/*
Copyright (c) 2010 Ben Hendel-Doying

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

package world;

import game.ASCII;

import java.util.ArrayList;
import java.util.Iterator;

public class Actor
{
	public static final int STEPS_TO_RECOVER_1_HP = 10;
	public static final int STARTING_HP = 10;

	public static final int INTELLIGENCE_ARTIFICIAL = 0;
	public static final int INTELLIGENCE_HUMAN = 1;

	public static final int REQUEST_INPUT_NONE = 0;
	public static final int REQUEST_INPUT_GATE = 1;
	public static final int REQUEST_INPUT_SHOP = 2;

	public static final Appearance DEFAULT_APPEARANCE = new Appearance('@', ASCII.COLOR_WHITE);

	protected String name = "";

	protected Attributes attributes = new Attributes();
	protected int HP_current;

	protected int experience = 0;

	protected ArrayList<Item> inventory = new ArrayList<Item>();
	protected ArrayList<Gate> gates = new ArrayList<Gate>();
	protected ArrayList<Buff> buffs = new ArrayList<Buff>();
	protected int obol = 0;

	protected Sword sword = null;
	protected Shield shield = null;
	protected Robes robes = null;

	protected Appearance appearance = DEFAULT_APPEARANCE;

	protected Tile location = null;

	protected boolean changed_rooms = false;

	protected int resting = STEPS_TO_RECOVER_1_HP;

	protected ArrayList<String> messages = new ArrayList<String>();

	protected int kills = 0;
	protected int miracle_heals = 0;
	protected int miracle_equipment = 0;

	protected int intelligence;

	protected int request_input = 0;
	protected Object request_object = null;

	Actor(int intelligence)
	{
		attributes.attack = 1;
		attributes.dodge = 1;
		attributes.PP = 1;

		HP_current = GetMaxHP();

		this.intelligence = intelligence;
	}

	public boolean ChangedRooms()
	{
		if(changed_rooms)
		{
			changed_rooms = false;
			return true;
		}
		else
			return false;
	}

	public boolean IsDead() { return(HP_current <= 0); }

	public void SetName(String n) { name = n; }
	public String GetName() { return name; }

	final public void SetTile(Tile t) { location = t; }
	final public Tile GetTile() { return location; }

	final public int GetX() { return location.GetX(); }
	final public int GetY() { return location.GetY(); }

	public boolean MoveTo(Gate g)
	{
		Tile t = g.GetTile();

		if(!t.GetNorth().IsBlocking() && t.GetNorth().GetCreature() == null)
		{
			MoveTo(t.GetNorth());
			return true;
		}

		if(!t.GetNE().IsBlocking() && t.GetNE().GetCreature() == null)
		{
			MoveTo(t.GetNE());
			return true;
		}

		if(!t.GetEast().IsBlocking() && t.GetEast().GetCreature() == null)
		{
			MoveTo(t.GetEast());
			return true;
		}

		if(!t.GetSE().IsBlocking() && t.GetSE().GetCreature() == null)
		{
			MoveTo(t.GetSE());
			return true;
		}

		if(!t.GetSouth().IsBlocking() && t.GetSouth().GetCreature() == null)
		{
			MoveTo(t.GetSouth());
			return true;
		}

		if(!t.GetSW().IsBlocking() && t.GetSW().GetCreature() == null)
		{
			MoveTo(t.GetSW());
			return true;
		}

		if(!t.GetWest().IsBlocking() && t.GetWest().GetCreature() == null)
		{
			MoveTo(t.GetWest());
			return true;
		}

		if(!t.GetNW().IsBlocking() && t.GetNW().GetCreature() == null)
		{
			MoveTo(t.GetNW());
			return true;
		}

		return false;
	}

	private final boolean MoveTo(Tile t)
	{
		if(t == null)
			return false;
		else if(t.IsBlocking())
			return Interact(t.GetScenery());
		else if(t.GetCreature() != null)
		{
			Attack(t.GetCreature());
			return true;
		}
		else
		{
			t.AddCreature(this);
			return true;
		}
	}

	// return "true" if an action was taken
	final public boolean MoveNorth() { return MoveTo(location.GetNorth()); }
	final public boolean MoveEast() { return MoveTo(location.GetEast()); }
	final public boolean MoveSouth() { return MoveTo(location.GetSouth()); }
	final public boolean MoveWest() { return MoveTo(location.GetWest()); }
	final public boolean MoveNE() { return MoveTo(location.GetNE()); }
	final public boolean MoveSE() { return MoveTo(location.GetSE()); }
	final public boolean MoveSW() { return MoveTo(location.GetSW()); }
	final public boolean MoveNW() { return MoveTo(location.GetNW()); }

	public void Attack(Actor t)
	{
		if(t.IsDead())
		{
			Tell(GetName() + " is already dead.");
			return;
		}

		final int fire_damage = GetFireDamage() - t.GetFireResistance();
		final int light_damage = GetLightDamage() - t.GetLightResistance();
		final int dark_damage = GetDarkDamage() - t.GetDarkResistance();

		final int total_damage = Math.max(0, fire_damage) + Math.max(0, light_damage) + Math.max(0, dark_damage) + World.RNG.nextInt(3) - 1;

		final int chance_to_get_blocked = t.GetBlock() * 100 / (t.GetBlock() + GetAttack());
		final int chance_to_get_dodged = t.GetDodge() * 100 / (t.GetDodge() + GetAttack());

		if(total_damage <= 0)
		{
			t.Tell(GetName() + " attacks you ineffectually.");
			Tell("You attack " + t.GetName() + " ineffectually.");
		}
		else if(t.GetShield() != null && World.RNG.nextInt(100) <= chance_to_get_blocked)
		{
			t.Tell(GetName() + " attacks you, but you block!");
			Tell("You attack " + t.GetName() + ", but it blocks!");

			if(t.GetShield().Damage(total_damage))
			{
				t.Tell("Your shield breaks!");
				Tell(t.GetName() + "'s shield breaks!");
				t.shield = null;
			}
		}
		else if(World.RNG.nextInt(100) <= chance_to_get_dodged)
		{
			t.Tell(GetName() + " attacks you, but you dodge!");
			Tell("You attack " + t.GetName() + ", but it dodges!");
		}
		else
		{
			if(t.Damage(total_damage, this))
			{
				GainExperience(t.GetExperience());
				kills++;
			}
		}
	}

	final public int GetKills() { return kills; }
	final public void ResetKill() { kills = 0; }

	final public void GainExperience(int a)
	{
		experience += a;
	}

	final public void SpendExperience(int a)
	{
		experience -= a;
	}

	final public Shield GetShield() { return shield; }
	final public Sword GetSword() { return sword; }
	final public Robes GetRobes() { return robes; }

	final public World GetWorld() { return GetTile().GetWorld(); }

	public boolean Damage(int d, Actor a)
	{
		if(IsDead())
			return false;

		Tell(a.GetName() + " hits you for " + d + " damage!");
		a.Tell("You hit " + GetName() + " for " + d + " damage.");

		if(d >= HP_current)
		{
			Tell("You die!");
			a.Tell(GetName() + " dies!");

			HP_current = 0;

			DropInventory();
			DropObol();

			GetWorld().RemoveMonster(this);
			location.RemoveCreature();

			return true;
		}
		else
		{
			HP_current -= d;

			return false;
		}
	}

	public int Heal(int d)
	{
		if(IsDead())
			return 0;

		if(HP_current + d >= GetMaxHP())
			d = GetMaxHP() - HP_current;

		HP_current += d;

		return d;
	}

	final public void Tell(String s) { messages.add(s); }

	final public boolean HasMessages() { return(messages.size() > 0); }

	final public String GetMessage()
	{
		if(HasMessages())
		{
			String s = messages.get(0);
			messages.remove(0);
			return s;
		}
		else
			return null;
	}

	final public boolean Interact(Scenery t) { return t.Act(this); }

	final public int GetExperience() { return experience; }

	final public int GetPP() { return attributes.PP; }
	final public int GetPS() { return attributes.PS; }
	final public int GetPE() { return attributes.PE; }
	final public int GetMP() { return attributes.MP; }
	final public int GetMS() { return attributes.MS; }
	final public int GetME() { return attributes.ME; }

	final public int GetBaseAttack() { return attributes.attack; }
	final public int GetBaseBlock() { return attributes.block; }
	final public int GetBaseDodge() { return attributes.dodge; }
	final public int GetBaseHeal() { return attributes.heal; }
	final public int GetBasePray() { return attributes.pray; }
	final public int GetBaseBless() { return attributes.bless; }
	final public int GetBaseGehenna() { return attributes.gehenna; }

	final public int GetAttack()
	{
		int a = GetPS() + attributes.attack;

		if(sword != null) a += sword.GetAttack();
		if(shield != null) a += shield.GetAttack();
		if(robes != null) a += robes.GetAttack();

		a += GetAttackBuffs();

		return a + GetPS();
	}

	final public int GetBlock()
	{
		int a = GetPS() + attributes.block;

		if(sword != null) a += sword.GetBlock();
		if(shield != null) a += shield.GetBlock();
		if(robes != null) a += robes.GetBlock();

		a += GetBlockBuffs();

		return a;
	}

	final public int GetDodge()
	{
		int a = GetPS() + attributes.dodge;

		if(sword != null) a += sword.GetDodge();
		if(shield != null) a += shield.GetDodge();
		if(robes != null) a += robes.GetDodge();

		a += GetDodgeBuffs();

		return a;
	}

	final public int GetHeal()
	{
		int a = Math.min(GetMP(), GetPE()) + attributes.heal;

		if(sword != null) a += sword.GetHeal();
		if(shield != null) a += shield.GetHeal();
		if(robes != null) a += robes.GetHeal();

		a += GetHealBuffs();

		return a;
	}

	final public int GetPray()
	{
		int a = GetMP() + attributes.pray;

		if(sword != null) a += sword.GetPray();
		if(shield != null) a += shield.GetPray();
		if(robes != null) a += robes.GetPray();

		a += GetPrayBuffs();

		return a;
	}

	final public int GetBless()
	{
		int a = GetMP() + attributes.bless;

		if(sword != null) a += sword.GetBless();
		if(shield != null) a += shield.GetBless();
		if(robes != null) a += robes.GetBless();

		a += GetBlessBuffs();

		return a;
	}

	final public int GetGehenna()
	{
		int a = GetMP() + attributes.gehenna;

		if(sword != null) a += sword.GetGehenna();
		if(shield != null) a += shield.GetGehenna();
		if(robes != null) a += robes.GetGehenna();

		a += GetGehennaBuffs();

		return a;
	}

	final public int GetMaxHP()
	{
		int a = STARTING_HP + attributes.HP_maximum;

		if(sword != null) a += sword.GetMaxHP();
		if(shield != null) a += shield.GetMaxHP();
		if(robes != null) a += robes.GetMaxHP();

		a += GetMaxHPBuffs();

		return a;
	}

	final public int GetBaseMaxHP() { return STARTING_HP + attributes.HP_maximum; }

	final public int GetFireDamage()
	{
		int a = Math.max(GetMP(), GetPP()) + attributes.damage_fire;

		if(sword != null) a += sword.GetFireDamage();
		if(shield != null) a += shield.GetFireDamage();
		if(robes != null) a += robes.GetFireDamage();

		a += GetFireDamageBuffs();

		return a;
	}

	final public int GetLightDamage()
	{
		int a = GetMP() + attributes.damage_light;

		if(sword != null) a += sword.GetLightDamage();
		if(shield != null) a += shield.GetLightDamage();
		if(robes != null) a += robes.GetLightDamage();

		a += GetLightDamageBuffs();

		return a;
	}

	final public int GetDarkDamage()
	{
		int a = GetPP() + attributes.damage_dark;

		if(sword != null) a += sword.GetDarkDamage();
		if(shield != null) a += shield.GetDarkDamage();
		if(robes != null) a += robes.GetDarkDamage();

		a += GetDarkDamageBuffs();

		return a;
	}

	final public int GetFireResistance()
	{
		int a = Math.max(GetME(), GetPE()) + attributes.resist_fire;

		if(sword != null) a += sword.GetFireResistance();
		if(shield != null) a += shield.GetFireResistance();
		if(robes != null) a += robes.GetFireResistance();

		a += GetFireResistanceBuffs();

		return a;
	}

	final public int GetLightResistance()
	{
		int a = GetME() + attributes.resist_light;

		if(sword != null) a += sword.GetLightResistance();
		if(shield != null) a += shield.GetLightResistance();
		if(robes != null) a += robes.GetLightResistance();

		a += GetLightResistanceBuffs();

		return a;
	}

	final public int GetDarkResistance()
	{
		int a = GetPE() + attributes.resist_dark;

		if(sword != null) a += sword.GetDarkResistance();
		if(shield != null) a += shield.GetDarkResistance();
		if(robes != null) a += robes.GetDarkResistance();

		a += GetDarkResistanceBuffs();

		return a;
	}

	final public int GetHP() { return HP_current; }

	public void Explore()
	{
		if(IsDead()) return;

		World w = GetWorld();
		w.CreateAdjacentTiles(location, true);

		if(location.GetNorth().IsTransparent()) w.CreateAdjacentTiles(location.GetNorth(), true);
		if(location.GetEast().IsTransparent()) w.CreateAdjacentTiles(location.GetEast(), true);
		if(location.GetSouth().IsTransparent()) w.CreateAdjacentTiles(location.GetSouth(), true);
		if(location.GetWest().IsTransparent()) w.CreateAdjacentTiles(location.GetWest(), true);
	}

	// chase after - and attack - a player
	public void Hunt(Actor a)
	{
		if(IsDead()) return;

		int n = Seek(location.GetNorth(), a, 6);
		int ne = Seek(location.GetNE(), a, 6);
		int e = Seek(location.GetEast(), a, 6);
		int se = Seek(location.GetSE(), a, 6);
		int s = Seek(location.GetSouth(), a, 6);
		int sw = Seek(location.GetSW(), a, 6);
		int w = Seek(location.GetWest(), a, 6);
		int nw = Seek(location.GetNW(), a, 6);

		if(n <= ne && n < e && n <= se && n < s && n <= sw && n < w && n <= nw)
			MoveNorth();
		else if(e < n && e <= ne && e <= se && e < s && e <= sw && e < w && e <= nw)
			MoveEast();
		else if(s < n && s <= ne && s < e && s <= se && s <= sw && s < w && s <= nw)
			MoveSouth();
		else if(w < n && w <= ne && w < e && w <= se && w < s && w <= sw && w <= nw)
			MoveWest();
		else if(ne <= se && ne <= sw && ne <= nw)
			MoveNE();
		else if(se <= ne && se <= sw && se <= nw)
			MoveSE();
		else if(sw <= ne && sw <= ne && sw <= nw)
			MoveSW();
		else if(nw <= ne && nw <= ne && nw <= sw)
			MoveNW();
	}

	private static final int ShortestRoute(int a, int b, int c, int d, int e, int f, int g, int h)
	{
		return Math.min(a, Math.min(b, Math.min(c, Math.min(d, Math.min(e, Math.min(f, Math.min(g, h)))))));
	}

	public int Seek(Tile t, Actor a, int max_steps)
	{
		// navigate around empty spaces, and solid spaces
		if(t == null || t.IsBlocking())
			return 10000;

		// navigate around friendly creatures
		if(t.GetCreature() != null && t.GetCreature() != a)
			return 10000;

		if(t.GetCreature() == a)
			return 0;
		else if(max_steps > 0)
		{
			int n = Seek(t.GetNorth(), a, max_steps - 1);
			int ne = Seek(t.GetNE(), a, max_steps - 1);
			int e = Seek(t.GetEast(), a, max_steps - 1);
			int se = Seek(t.GetSE(), a, max_steps - 1);
			int s = Seek(t.GetSouth(), a, max_steps - 1);
			int sw = Seek(t.GetSW(), a, max_steps - 1);
			int w = Seek(t.GetWest(), a, max_steps - 1);
			int nw = Seek(t.GetNW(), a, max_steps - 1);

			return ShortestRoute(n, ne, e, se, s, sw, w, nw) + 1;
		}
		else
			return 10;
	}

	public void EquipSword(Sword i)
	{
		if(i != null && !inventory.contains(i))
			inventory.add(i);

		sword = i;
	}

	public void EquipShield(Shield i)
	{
		if(i != null && !inventory.contains(i))
			inventory.add(i);


		shield = i;
	}

	public void EquipRobes(Robes i)
	{
		if(i != null && !inventory.contains(i))
			inventory.add(i);

		robes = i;
	}

	public void PickUp(Item i)
	{
		inventory.add(i);
	}

	public boolean PickUp()
	{
		boolean step = false;
		int o = location.TakeObol();

		if(o > 0)
		{
			obol += o;
			Tell("Picked up " + o + " Obol.");
			step = true;
		}

		int n = location.ItemCount();

		if(n > 0)
		{
			if(inventory.size() >= 10)
				Tell("You can't carry any more.");
			else
			{

				int c = 0;

				if(inventory.size() + n > 10)
				{
					while(inventory.size() < 10)
					{
						Item i = location.GetFirstItem();
						inventory.add(i);
						location.RemoveFirstItem();
						c++;
					}
				}
				else
				{
					inventory.addAll(location.GetItems());
					location.ClearItems();
					c = n;
				}

				if(c == 1)
					Tell("Picked up the " + inventory.get(inventory.size() - 1).GetName() + ".");
				else
					Tell("Picked up " + c + " items.");

				if(c < n)
					Tell("You could not pick up all of the items.");

				step = true;
			}
		}
		else if(o == 0)
			Tell("There's nothing to pick up here.");

		return step;
	}

	final public boolean Rest()
	{
		int rest = GetHeal();

		resting -= (rest + 1);

		while(resting < 0)
		{
			resting += STEPS_TO_RECOVER_1_HP;
			Heal(1);
		}

		return true;
	}

	public boolean Search()
	{
		boolean step = false;
		boolean result = false;

		Scenery s;

		s = location.GetNorth().GetScenery();

		if(s instanceof Wall)
		{
			step = true;

			result = result || ((Wall)s).Search(this);
		}

		s = location.GetNE().GetScenery();

		if(s instanceof Wall)
		{
			step = true;

			result = result || ((Wall)s).Search(this);
		}

		s = location.GetEast().GetScenery();

		if(s instanceof Wall)
		{
			step = true;

			result = result || ((Wall)s).Search(this);
		}

		s = location.GetSE().GetScenery();

		if(s instanceof Wall)
		{
			step = true;

			result = result || ((Wall)s).Search(this);
		}

		s = location.GetSouth().GetScenery();

		if(s instanceof Wall)
		{
			step = true;

			result = result || ((Wall)s).Search(this);
		}

		s = location.GetSW().GetScenery();

		if(s instanceof Wall)
		{
			step = true;

			result = result || ((Wall)s).Search(this);
		}

		s = location.GetWest().GetScenery();

		if(s instanceof Wall)
		{
			step = true;

			result = result || ((Wall)s).Search(this);
		}

		s = location.GetNW().GetScenery();

		if(s instanceof Wall)
		{
			step = true;

			result = result || ((Wall)s).Search(this);
		}

		if(step)
		{
			if(!result)
				Tell("You didn't find anything.");
		}
		else
			Tell("There are no walls to search here.");

		return step;
	}

	final public ArrayList<Item> GetInventory() { return inventory; }
	final public Item GetInventory(int a){ return inventory.get(a); }

	public boolean DestroyInventory(Item i)
	{
		return inventory.remove(i);
	}

	public boolean DropInventory(int a)
	{
		Item i = inventory.get(a);

		if(i == null)
			return false;

		if(sword == i)
			EquipSword(null);
		if(shield == i)
			EquipShield(null);
		if(robes == i)
			EquipRobes(null);

		inventory.remove(a);

		location.AddItem(i);

		Tell("You drop the " + i.GetName() + ".");

		return true;
	}

	public void DropInventory()
	{
		sword = null;
		shield = null;
		robes = null;

		while(inventory.size() > 0)
			DropInventory(0);
	}

	public void DropObol()
	{
		if(obol > 0)
		{
			location.AddObol(obol);
			obol = 0;
		}
	}

	final public boolean IsEquippedWith(Item i)
	{
		return(sword == i || shield == i || robes == i);
	}

	final public void MemorizeGate(Gate t) { gates.add(t); }

	final public ArrayList<Gate> GetKnownGates() { return gates; }

	final public Gate GetKnownGate(int i) { return gates.get(i); }

	final public int GetKnownGateCount() { return gates.size(); }

	public void PerformMiracleHeal()
	{
		HP_current = GetMaxHP();

		Tell("You've been miraclously healed!");

		miracle_heals++;
	}

	public int MiracleHealCost()
	{
		return miracle_heals * 2;
	}

	public void PerformMiracleEquipment()
	{
		Item i = GetWorld().CreateEquipment(miracle_equipment + 2);
		inventory.add(i);

		Tell("You receive " + i.GetName() + "!");

		miracle_equipment++;
	}

	public int MiracleEquipmentCost()
	{
		return miracle_equipment * 4;
	}

	final public void IncrementPP() { attributes.PP++; }
	final public void IncrementPS() { attributes.PS++; }
	final public void IncrementPE() { attributes.PE++; }
	final public void IncrementMP() { attributes.MP++; }
	final public void IncrementMS() { attributes.MS++; }
	final public void IncrementME() { attributes.ME++; }
	final public void IncrementAttack() { attributes.attack++; }
	final public void IncrementBlock() { attributes.block++; }
	final public void IncrementDodge() { attributes.dodge++; }
	final public void IncrementHeal() { attributes.heal++; }
	final public void IncrementPray() { attributes.pray++; }
	final public void IncrementBless() { attributes.bless++; }
	final public void IncrementGehenna() { attributes.gehenna++; }
	final public void IncrementMaxHP() { attributes.HP_maximum++; HP_current++; }

	public boolean UseGate(Gate g)
	{
		if(gates.size() < 2)
		{
			Tell("You do not know of any other gates.");
			return false;
		}
		else
		{
			if(intelligence == INTELLIGENCE_HUMAN)
			{
				request_input = REQUEST_INPUT_GATE;
				request_object = g;
			}

			return false;
		}
	}

	public boolean UseShop(Shop s)
	{
		if(intelligence == INTELLIGENCE_HUMAN)
		{
			request_input = REQUEST_INPUT_SHOP;
			request_object = s;
		}

		return false;
	}

	final public void ClearRequest() { request_input = REQUEST_INPUT_NONE; request_object = null; }
	final public int RequestingInput() { return request_input; }
	final public Object RequestingObject() { return request_object; }

	public boolean CloseDoor()
	{
		if(location.GetNorth().GetScenery() != null && location.GetNorth().GetScenery() instanceof Door && !location.GetNorth().GetScenery().IsBlocking())
		{
			location.GetNorth().GetScenery().Act(this);
			return true;
		}

		if(location.GetNE().GetScenery() != null && location.GetNE().GetScenery() instanceof Door && !location.GetNE().GetScenery().IsBlocking())
		{
			location.GetNE().GetScenery().Act(this);
			return true;
		}

		if(location.GetEast().GetScenery() != null && location.GetEast().GetScenery() instanceof Door && !location.GetEast().GetScenery().IsBlocking())
		{
			location.GetEast().GetScenery().Act(this);
			return true;
		}

		if(location.GetSE().GetScenery() != null && location.GetSE().GetScenery() instanceof Door && !location.GetSE().GetScenery().IsBlocking())
		{
			location.GetSE().GetScenery().Act(this);
			return true;
		}

		if(location.GetSouth().GetScenery() != null && location.GetSouth().GetScenery() instanceof Door && !location.GetSouth().GetScenery().IsBlocking())
		{
			location.GetSouth().GetScenery().Act(this);
			return true;
		}

		if(location.GetSW().GetScenery() != null && location.GetSW().GetScenery() instanceof Door && !location.GetSW().GetScenery().IsBlocking())
		{
			location.GetSW().GetScenery().Act(this);
			return true;
		}

		if(location.GetWest().GetScenery() != null && location.GetWest().GetScenery() instanceof Door && !location.GetWest().GetScenery().IsBlocking())
		{
			location.GetWest().GetScenery().Act(this);
			return true;
		}

		if(location.GetNW().GetScenery() != null && location.GetNW().GetScenery() instanceof Door && !location.GetNW().GetScenery().IsBlocking())
		{
			location.GetNW().GetScenery().Act(this);
			return true;
		}

		Tell("There are no open doors nearby.");

		return false;
	}

	public void Step()
	{
		Iterator<Buff> i = buffs.iterator();

		while(i.hasNext())
		{
			Buff b = i.next();

			b.Step();

			if(b.IsDead())
			{
				Tell("The " + b.GetName() + " wears off.");
				i.remove();
			}
		}
	}

	final public ArrayList<Buff> GetBuffs() { return buffs; }

	final public int GetAttackBuffs()
	{
		if(buffs.size() == 0) return 0;

		Iterator<Buff> i = buffs.iterator();
		int total = 0;

		while(i.hasNext())
		{
			Buff b = i.next();
			total = b.attack;
		}

		return total;
	}

	final public int GetDodgeBuffs()
	{
		if(buffs.size() == 0) return 0;

		Iterator<Buff> i = buffs.iterator();
		int total = 0;

		while(i.hasNext())
		{
			Buff b = i.next();
			total = b.dodge;
		}

		return total;
	}

	final public int GetBlockBuffs()
	{
		if(buffs.size() == 0) return 0;

		Iterator<Buff> i = buffs.iterator();
		int total = 0;

		while(i.hasNext())
		{
			Buff b = i.next();
			total = b.block;
		}

		return total;
	}

	final public int GetHealBuffs()
	{
		if(buffs.size() == 0) return 0;

		Iterator<Buff> i = buffs.iterator();
		int total = 0;

		while(i.hasNext())
		{
			Buff b = i.next();
			total = b.heal;
		}

		return total;
	}

	final public int GetPrayBuffs()
	{
		if(buffs.size() == 0) return 0;

		Iterator<Buff> i = buffs.iterator();
		int total = 0;

		while(i.hasNext())
		{
			Buff b = i.next();
			total = b.pray;
		}

		return total;
	}

	final public int GetBlessBuffs()
	{
		if(buffs.size() == 0) return 0;

		Iterator<Buff> i = buffs.iterator();
		int total = 0;

		while(i.hasNext())
		{
			Buff b = i.next();
			total = b.bless;
		}

		return total;
	}

	final public int GetGehennaBuffs()
	{
		if(buffs.size() == 0) return 0;

		Iterator<Buff> i = buffs.iterator();
		int total = 0;

		while(i.hasNext())
		{
			Buff b = i.next();
			total = b.gehenna;
		}

		return total;
	}

	final public int GetMaxHPBuffs()
	{
		if(buffs.size() == 0) return 0;

		Iterator<Buff> i = buffs.iterator();
		int total = 0;

		while(i.hasNext())
		{
			Buff b = i.next();
			total = b.HP_maximum;
		}

		return total;
	}

	final public int GetFireDamageBuffs()
	{
		if(buffs.size() == 0) return 0;

		Iterator<Buff> i = buffs.iterator();
		int total = 0;

		while(i.hasNext())
		{
			Buff b = i.next();
			total = b.damage_fire;
		}

		return total;
	}

	final public int GetLightDamageBuffs()
	{
		if(buffs.size() == 0) return 0;

		Iterator<Buff> i = buffs.iterator();
		int total = 0;

		while(i.hasNext())
		{
			Buff b = i.next();
			total = b.damage_light;
		}

		return total;
	}

	final public int GetDarkDamageBuffs()
	{
		if(buffs.size() == 0) return 0;

		Iterator<Buff> i = buffs.iterator();
		int total = 0;

		while(i.hasNext())
		{
			Buff b = i.next();
			total = b.damage_dark;
		}

		return total;
	}

	final public int GetFireResistanceBuffs()
	{
		if(buffs.size() == 0) return 0;

		Iterator<Buff> i = buffs.iterator();
		int total = 0;

		while(i.hasNext())
		{
			Buff b = i.next();
			total = b.resist_fire;
		}

		return total;
	}

	final public int GetLightResistanceBuffs()
	{
		if(buffs.size() == 0) return 0;

		Iterator<Buff> i = buffs.iterator();
		int total = 0;

		while(i.hasNext())
		{
			Buff b = i.next();
			total = b.resist_light;
		}

		return total;
	}

	final public int GetDarkResistanceBuffs()
	{
		if(buffs.size() == 0) return 0;

		Iterator<Buff> i = buffs.iterator();
		int total = 0;

		while(i.hasNext())
		{
			Buff b = i.next();
			total = b.resist_dark;
		}

		return total;
	}

	final public void AddBuff(Buff b)
	{
		buffs.add(b);
	}

	final public int GetObol() { return obol; }
	final public void SpendObol(int a) { obol -= a; }
	final public void EarnObol(int a) { obol += a; }
}
